﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.ServiceModel.Configuration;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Core.Helper;
using Core.Model;
using Core.Model.Transmit;

namespace DataServer.Config
{
    public static class ConfigManager
    {
        private static readonly string configFilePath = AppDomain.CurrentDomain.BaseDirectory +
                                                        Properties.Resources.configpath;

        private static readonly string operationPath = AppDomain.CurrentDomain.BaseDirectory +
                                                       Properties.Resources.operationpath;

        private static readonly string deviceConfigPath = AppDomain.CurrentDomain.BaseDirectory +
                                                       Properties.Resources.deviceconfigpath;

        /// <summary>
        /// 更新WCF客户端服务地址
        /// </summary>
        /// <param name="serverIPAddress"></param>
        /// <param name="serverPort"></param>
        public static void UpdateWcfClientConfig(string serverIPAddress, string serverPort)
        {
            //Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);  
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSectionGroup sct = config.SectionGroups["system.serviceModel"];
            ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
            if (serviceModelSectionGroup != null)
            {
                ClientSection clientSection = serviceModelSectionGroup.Client;

                foreach (ChannelEndpointElement item in clientSection.Endpoints)
                {
                    string pattern = "://.*/";
                    string address = item.Address.ToString();
                    string replacement = $"://{serverIPAddress}:{serverPort}/";
                    address = Regex.Replace(address, pattern, replacement);
                    item.Address = new Uri(address);
                }
            }
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("system.serviceModel");
        }


        /// <summary>
        /// 获取WCF服务端服务地址
        /// </summary>
        /// <returns></returns>
        public static IPEndPoint GetServiceWcfConfig()
        {
            //Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);  
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationManager.RefreshSection("system.serviceModel");
            ConfigurationSectionGroup sct = config.SectionGroups["system.serviceModel"];
            ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
            if (serviceModelSectionGroup != null)
            {
                var serviceSection = serviceModelSectionGroup.Services;

                foreach (ServiceElement sss in serviceSection.Services)
                {
                    var item = sss.Host;
                    string pattern = "//.*/";
                    string address = item.BaseAddresses[0].BaseAddress;
                    Match match = Regex.Match(address, pattern);
                    if (!string.IsNullOrEmpty(match.Value))
                    {
                        string[] str = match.Value.Split(':');
                        int port = Int32.Parse(str[1].Substring(0, str[1].Length - 1));
                        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(str[0].Remove(0, 2)), port);
                        return ipEndPoint;
                    }
                }
            }
            return null;
        }

        public static string GetWcfBaseAddress()
        {
            //Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);  
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationManager.RefreshSection("system.serviceModel");
            ConfigurationSectionGroup sct = config.SectionGroups["system.serviceModel"];
            ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
            if (serviceModelSectionGroup != null)
            {
                var serviceSection = serviceModelSectionGroup.Services;

                foreach (ServiceElement sss in serviceSection.Services)
                {
                    var item = sss.Host;

                    return item.BaseAddresses[0].BaseAddress;
                }
            }
            return null;
        }

        /// <summary>
        /// 更新WCF服务器的服务地址
        /// </summary>
        /// <param name="serverIPAddress"></param>
        /// <param name="serverPort"></param>
        public static bool UpdateServiceWcfConfig(string serverIPAddress, int serverPort)
        {
            try
            {
                //Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);  
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                ConfigurationSectionGroup sct = config.SectionGroups["system.serviceModel"];
                ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
                if (serviceModelSectionGroup != null)
                {
                    var serviceSection = serviceModelSectionGroup.Services;

                    foreach (ServiceElement sss in serviceSection.Services)
                    {
                        var item = sss.Host;
                        string pattern = "://.*/";
                        string address = item.BaseAddresses[0].BaseAddress;
                        string replacement = $"://{serverIPAddress}:{serverPort}/";
                        address = Regex.Replace(address, pattern, replacement);
                        item.BaseAddresses[0].BaseAddress = address;
                    }
                }
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("system.serviceModel");
            }
            catch
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 读取App.config配置
        /// </summary>
        /// <param name="strKey"></param>
        /// <returns></returns>
        public static string GetAppConfig(string strKey)
        {
            try
            {
                foreach (string key in ConfigurationManager.AppSettings)
                {
                    if (key == strKey)
                    {
                        ConfigurationManager.RefreshSection(key);
                        return ConfigurationManager.AppSettings[strKey];
                    }
                }
            }
            catch
            {

            }
            return null;
        }

        /// <summary>
        /// 更新App.config 配置信息
        /// </summary>
        /// <param name="newKey"></param>
        /// <param name="newValue"></param>
        public static void UpdateAppConfig(string newKey, string newValue)
        {
            bool isModified = false;
            foreach (string key in ConfigurationManager.AppSettings)
            {
                if (key == newKey)
                {
                    isModified = true;
                }
            }

            // Open App.Config of executable
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // You need to remove the old settings object before you can replace it
            if (isModified)
            {
                config.AppSettings.Settings.Remove(newKey);
            }
            // Add an Application Setting. 
            config.AppSettings.Settings.Add(newKey, newValue);
            // Save the changes in App.config file. 
            config.Save(ConfigurationSaveMode.Modified);
            // Force a reload of a changed section.
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 获取 默认Ip
        /// </summary>
        /// <returns></returns>
        public static string GetDefaultIp()
        {
            IniFile iniFile = new IniFile(configFilePath);
            return iniFile.GetValue("本地信息", "默认IP", "192.168.1.100");
        }

        /// <summary>
        /// 导入操作信息
        /// </summary>
        /// <returns></returns>
        public static List<Operation> ImportOperations()
        {
            List<Operation> operations = new List<Operation>();
            OpenFileDialog ofDlg = new OpenFileDialog();
            //ofDlg.InitialDirectory = operationpath;
            ofDlg.Filter = "命令信息文件(.ini)|*.ini";
            ofDlg.Multiselect = false;
            if (ofDlg.ShowDialog() == DialogResult.OK)
            {
                IniFile iniTemplate = new IniFile(ofDlg.FileName);
                int count = iniTemplate.GetValue("操作信息", "总个数", 0);
                for (int i = 0; i < count; i++)
                {
                    try
                    {
                        var strDataItem = iniTemplate.GetValue("操作信息", "操作项_" + i.ToString("D2"), "");
                        string[] datas = strDataItem.Split('_');
                        if (datas.Length != 6)
                        {
                            continue;
                        }
                        Operation operation = new Operation();
                        operation.Id = datas[0];
                        operation.Name = datas[1];
                        operation.IsAscii = bool.Parse(datas[2]);
                        operation.NeedReply = bool.Parse(datas[3]);
                        operation.Timeout = Int32.Parse(datas[4]);
                        operation.MsgContent = datas[5];
                        operations.Add(operation);
                    }
                    catch
                    {
                    }
                }
            }
            return operations;
        }
        /// <summary>
        /// 导出操作信息
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="operations"></param>
        /// <returns></returns>
        public static bool ExportOperations(string filename,List<Operation> operations)
        {
            if (operations == null || operations.Count == 0)
                return false;
            //选择创建文件的路径
            SaveFileDialog save = new SaveFileDialog();
            save.DefaultExt = "ini";
            save.AddExtension = true;
            save.Filter = "命令信息文件(.ini)|*.ini";
            save.Title = "请选择要导出数据的位置";
            save.FileName = filename;
            //save.InitialDirectory = operationpath;
         
            if (save.ShowDialog() == DialogResult.OK)
            {
                IniFile iniTemplate = new IniFile(save.FileName);
                iniTemplate.ClearAllSection();
                iniTemplate.WriteValue("操作信息", "总个数", operations.Count);
                for (int i = 0; i < operations.Count; i++)
                {
                    try
                    {
                        string content = $"{operations[i].Id}_{operations[i].Name}_{operations[i].IsAscii}_{operations[i].NeedReply}_{operations[i].Timeout}_{operations[i].MsgContent}";
                        iniTemplate.WriteValue("操作信息", "操作项_" + i.ToString("D2"), content);
                    }
                    catch
                    {
                        return false;
                    }
                }
                iniTemplate.Save();
            }
            return true;
        }
        public static bool ExportDeviceConfig(Device dev,List<DataItem> dataItems)
        {
            if (dev==null|| dataItems == null || dataItems.Count == 0)
                return false;
            //选择创建文件的路径
            SaveFileDialog save = new SaveFileDialog();
            save.DefaultExt = "ini";
            save.AddExtension = true;
            save.Filter = "设备配置信息(.ini)|*.ini";
            save.Title = "请选择要导出信息的位置";
            save.FileName = dev.Name;
            save.InitialDirectory = deviceConfigPath;

            if (save.ShowDialog() == DialogResult.OK)
            {
                IniFile iniTemplate = new IniFile(save.FileName);
                iniTemplate.ClearAllSection();
                iniTemplate.WriteValue("设备信息", "设备名称", dev.Name);
                iniTemplate.WriteValue("设备信息", "字节顺序", dev.ByteOrder.ToString());
                iniTemplate.WriteValue("设备信息", "通信中断", dev.BreakCount);
                iniTemplate.WriteValue("设备信息", "通信协议", dev.Protocol);
                iniTemplate.WriteValue("设备信息", "通信地址", dev.Address);
                iniTemplate.WriteValue("设备信息", "设备类型", dev.DeviceTypeId);
                iniTemplate.WriteValue("数据项信息", "总个数", dataItems.Count);
                for (int i = 0; i < dataItems.Count; i++)
                {
                    try
                    {
                        string content = $"{dataItems[i].Position}_{dataItems[i].Name}_{dataItems[i].Address}_{dataItems[i].Category}_{dataItems[i].Access}_{dataItems[i].DataType}_"+
                            $"{dataItems[i].PhyType}_{dataItems[i].IsStorage}_{dataItems[i].StorageCycle}_{dataItems[i].TriggerValue}_{dataItems[i].SubInfo}";
                        iniTemplate.WriteValue("数据项信息", "数据项_" + i.ToString("D03"), content);
                    }
                    catch
                    {
                        return false;
                    }
                }
                iniTemplate.Save();
                MessageBox.Show("导出成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            return true;
        }

        public static List<DataItem>  ImportDeviceConfig(Device dev)
        {
            if (dev == null )
                return null;
            //选择创建文件的路径
            OpenFileDialog ofDlg = new OpenFileDialog();
            ofDlg.InitialDirectory = deviceConfigPath;
            ofDlg.Filter = "设备信息文件(.ini)|*.ini";
            ofDlg.Multiselect = false;
            if (ofDlg.ShowDialog() == DialogResult.OK)
            {
                List<DataItem> dataItems = new List<DataItem>();
                IniFile iniTemplate = new IniFile(ofDlg.FileName);
                dev.Name = iniTemplate.GetValue("设备信息", "设备名称","设备名称");
                dev.ByteOrder = (ByteOrder)Enum.Parse(typeof(ByteOrder),iniTemplate.GetValue("设备信息", "字节顺序", ByteOrder.高位在前.ToString()));
                dev.BreakCount = iniTemplate.GetValue("设备信息", "通信中断", 3);
                dev.Protocol = iniTemplate.GetValue("设备信息", "通信协议", "CommonProtocol");
                dev.Address = iniTemplate.GetValue("设备信息", "通信地址", 1ul);
                dev.DeviceTypeId = iniTemplate.GetValue("设备信息", "设备类型", "");
                dev.IsWork = true;
                int count = iniTemplate.GetValue("数据项信息", "总个数", 1);
                for (int i = 0; i < count; i++)
                {
                    try
                    {
                        string content = iniTemplate.GetValue("数据项信息", "数据项_" + i.ToString("D03"), "");
                        if(string.IsNullOrEmpty(content)) continue;
                        string[] item = content.Split('_');
                        DataItem dataItem = new DataItem();
                        dataItem.Position = Int32.Parse(item[0]);
                        dataItem.Name = item[1];
                        dataItem.DeviceId = dev.Id;
                        dataItem.Address = Int32.Parse(item[2]);
                        dataItem.Category = (Category)Enum.Parse(typeof(Category), item[3]);
                        dataItem.Access = (Access)Enum.Parse(typeof(Access), item[4]);
                        dataItem.DataType = (DataType)Enum.Parse(typeof(DataType), item[5]);
                        dataItem.PhyType = (PhyType)Enum.Parse(typeof(PhyType), item[6]);
                        dataItem.IsStorage = bool.Parse(item[7]);
                        dataItem.StorageCycle = Int32.Parse(item[8]);
                        dataItem.TriggerValue = Int32.Parse(item[9]);
                        dataItem.SubInfo = item[10];
                        dataItems.Add(dataItem);
                    }
                    catch
                    {
                    }
                }
                return dataItems;
            }
            return null;
        }

        public static bool ExportTransmitDeviceConfig(TransmitDevice dev, List<TransmitData> dataItems)
        {
            if (dev == null || dataItems == null || dataItems.Count == 0)
                return false;
            //选择创建文件的路径
            SaveFileDialog save = new SaveFileDialog();
            save.DefaultExt = "ini";
            save.AddExtension = true;
            save.Filter = "设备配置信息(.ini)|*.ini";
            save.Title = "请选择要导出信息的位置";
            save.FileName = dev.Name;
            save.InitialDirectory = deviceConfigPath;

            if (save.ShowDialog() == DialogResult.OK)
            {
                IniFile iniTemplate = new IniFile(save.FileName);
                iniTemplate.ClearAllSection();
                iniTemplate.WriteValue("设备信息", "设备名称", dev.Name);
                iniTemplate.WriteValue("设备信息", "字节顺序", dev.ByteOrder.ToString());
                iniTemplate.WriteValue("设备信息", "通信协议", dev.Protocol);
                iniTemplate.WriteValue("设备信息", "通信地址", dev.Address);
                iniTemplate.WriteValue("数据项信息", "总个数", dataItems.Count);
                for (int i = 0; i < dataItems.Count; i++)
                {
                    try
                    {
                        string content = $"数据名称：{dataItems[i].Name}，  数据地址：{dataItems[i].Address}，  数据种类:{dataItems[i].PhyType}，  数据类型：{dataItems[i].DataType}，  " +
                            $"数据倍率：{dataItems[i].Coefficient}";
                        iniTemplate.WriteValue("数据项信息", "数据项_" + i.ToString("D03"), content);
                    }
                    catch
                    {
                        return false;
                    }
                }
                iniTemplate.Save();
                MessageBox.Show("导出成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            return true;
        }


        public static T GetValueFromIni<T>(string section, string key,T defValue)
        {
            string valueType = typeof(T).Name.ToLower();
            IniFile iniFile = new IniFile(configFilePath);
            switch (valueType)
            {
                case "int16":
                    return  (T)Convert.ChangeType(iniFile.GetValue(section, key, Convert.ToInt16(defValue)), typeof(T)); 
                case "int32":
                    return (T)Convert.ChangeType(iniFile.GetValue(section, key, Convert.ToInt32(defValue)), typeof(T)); 
                case "string":
                    return (T)Convert.ChangeType(iniFile.GetValue(section, key,defValue.ToString()), typeof(T));
                case "boolean":
                    return (T)Convert.ChangeType(iniFile.GetValue(section, key, Convert.ToBoolean(defValue)), typeof(T));
                case "float":
                    return (T)Convert.ChangeType(iniFile.GetValue(section, key, Convert.ToDouble(defValue)), typeof(T));
                case "double":
                   return (T)Convert.ChangeType(iniFile.GetValue(section, key, Convert.ToDouble(defValue)), typeof(T));
                default:
                    return defValue;
            }
        }
    }
}
